GBC Hardware |
Specs |
|
CPU: 8-bit (Similar to the Z80 processor.)
at 4.194304 MHz for 'compatibility mode', 8.388MHz GBC Gameboy Color Mode
Main RAM: 8K Byte
Video RAM: 8K Byte
ROM: 256kBit, 512kBit, 1MBit, 2MBit and 4MBit up to 16 MBit (32kB,64kB,
128kB, 256kB, and 512kB up to 2MB)
Screen Size: 6.6 cm (2.6 inches)
Resolution: Reflective LCD at 160x144 pixels (20x18 tiles - 1 Tile
being defined as 8x8 pixels)
Colour: 56 Colours at one time from 32,768 (this comes from the
8 pallettes and 4 colours for the background (8x4 = 32) and the 8 pallettes
and 3 colours (since 1 of them is transparent) for the sprites (8x3 =
24) so 32 + 24 = 56).
Max # of sprites: 40
Max # sprites/line: 10
Max sprite size: 8x16
Min sprite size: 8x8
Horiz Sync: 9198 KHz (9420 KHz for SGB)
Vert Sync: 59.73 Hz (61.17 Hz for SGB)
Sound: 4 channels with stereo sound
|
Basic Concepts |
|
Interrupts
Let's first talk about interrupts. In case
you've forgotten, an interrupt is an event or signal that essentially
interrupts whatever code is running (in the 209 course you guys are doing,
you'll soon be talking about signals, which are just software interrupts).
Interrupts are important because they can provide some sort of timing
mechanism, or tell us when some hardware function has finished. For example,
in our gameboy programming, we'll want to update the graphics on screen
after the LCD is finished refreshing (essentially after its vertical blank).
What we do is when we code our game, we define interrupt handlers
to specific interrups - they are essentially functions that get called
when the interrupt occurs. So, when we're in our game loop, say updating
coordinate positions and the vblank interrupt occurs, our handler will
be called and do its thing (i.e. redraw the sprites) and when its done
we'll go right back to where we left off in our code. The good thing to
note is that the gameboy has only five interrupt signals.
- V-Blank - This interrupt can be generated
when the LCD has drawn the last line on the screen and gone into the
vertical blanking period, approximately 59.7 times a second. During
this period video hardware is not using video ram so it may be freely
accessed.
This period lasts approximately 1.1 milliseconds.
- LCDC - This interrupt
can be generated by the LCD controller chip on various conditions, the
most commonly used being the LYC condition, which occurs when the LCD
begins to draw a certain scanline. The scanline it generates an interrupt
on is selectable. (This can be used for special effects - but we probably
won't be using it at all).
- Timer - The system timer can be set to count
at specified frequencies, and will increment a count register. When
this register overflows, an interrupt is generated. One of its uses
is for sound playback.
- Serial - This interrupt occurs when a serial
transfer has completed on the game link port (we'll never use this).
- Joypad - This interrupt occurs on a transition
of any of the keypad input lines from high to low. Due to the fact that
keypad "bounce"* is virtually always present, software should
expect this interrupt to occur one or more times for every button press
and one or more times for every button release (I'm not sure when this
is used - maybe for some very sensitive gameplay I suppose. We'll be
using the regular joypad function).
Graphics
The Gameboy Color doesn't use APA (all points accessable)
graphics such as your computer uses. Instead it uses tiles to draw everything.
While this has certain advantages, it also makes simple things such as
drawing a line really difficult. The Gameboy Color uses 8x8 pixel tiles
to create the background. The Gameboy Color's screen has a resolution
of 20x18 tiles or 160x144 pixels. Inside its VRAM, in an area called the
Background Tile Map, it stores 32x32 tiles or 256x256 pixels. So
there is essentially a virtual screen of 16 extra tiles horizontally
and 14 tiles vertically. This is useful for games that scroll the background.
The Gameboy Color can display 256 unique tiles on the screen at one time.
It has an additional VRAM bank to display an additional 256 tiles, although
this kills any chance of backwards compatability with the original Gameboy.
(However, it is the case that essentially all 2D games use
tiles - even arcade games like Street Fighter II). Sprites are
tiles independant of the background. These are used for things such as
the main character and badguys. The Gameboy Color can display either 8x8
or 8x16 pixels per tile. It can display 40 sprites simultaniously. One
of its main drawbacks is that it can only display 10 sprites per horizontal
line. The Gameboy Color features a few hardware sprite manipulations.
While it does not feature resizing the sprites or more useful things,
you can flip the horizontal and vertical axis on each sprite. This is
useful to make a character walk in 2 directions without needing to load
a new tile into the sprite. The Gameboy Color can hold 256 8x8 pixel tiles
or 128 8x16 pixel tiles into sprite ram. This is useful since it takes
alot less computing power to change which ram location to display the
tile than to load a unique tile into its place. Notice that there are
only two layers on the GBC; the background and the
window. The window is a nontransparent layer that can be applied
on top of the background. It does not use its own palettes or tiles, but
rather shares them with the background's. The window is useful for things
such as pop-up maps, status bars that don't scroll with the background,
and many other uses.
To solidify everything, let's say that Tile data is
stored in VRAM and numbered 0 -127. Now a map is simply a 2D array whose
entries are just the array indices of each tile to be placed on a certain
area of the LCD, 0-127 in this case. So, the map area is a 32x32 byte
array (1024 bytes) that makes up the Background Map, or BGMAP for short.
The way the LCD draws a screen is this: it takes the byte value in the
map area, and gets the corressponding tile from the tile set, and draws
the 8x8 tile where it got the map byte from.
Now, the Sprite area of VRAM is divided into 40 blocks
of 4-bytes (where each 4-byte block defines a sprite, thus allowing only
40 sprites on the screen at once). The 4 bytes are laid out thus
Byte 0 |
Y Position on Screen |
Byte 1 |
X Position on Screen |
Byte 2 |
Tile number |
Byte 3 |
Flags:
BIT 7 Background Priority
BIT 6 Flip Tile Vertical
BIT 5 Flip Tile Horizontal
BIT 3 Character Bank select
BIT 0-2 Palettenumber (0-7)
|
ROMS
The ROMs we will compile represent a gameboy game
cartridge (i.e. solid state chip that encodes data without changing).
Cartridges come in varying sizes from 256kb to 16Mb (the writeable cartridge
I have is 16Mb). The GBC can read these bigger cartridges through subtle
trickery. What it amounts to is this; the GBC can only "see"
a 256Kbit (32KByte) cartridge. This basic cartridge can be subdivided
into two 16KByte pieces. The lower 16KByte piece is fixed, while the upper
16KByte piece is variable. What the gameboy does is look through
a window 16KByte wide, and keeps on sliding it over to see more data.
These 16KByte pieces are called banks. We can have up to 127
banks (for a 16Mbit cart). As you might have guessed, it's beneficial
(rather, mandatory) that we split our code amongst these banks. Also,
we have to switch to the proper bank manually, since it's not automatic.
So, we manually tell the gameboy which bank to switch to, and the gameboy
in turn envokes the memory bank controller (MBC) on the cartridge.
There were two major MBCs made for gb carts: MBC1 and MBC5 other
minor ones were MBC2 and MBC3.
|
Memory Map |
|
First of all note that the GBC uses an 8 bit CPU but
its address bus in 16 bits. What this means is that it can address a whopping
64KB of memory. To be painfully precise, that means it can address 0000000000000000
to 1111111111111111, or in hexadecimal (base 16) $0000 to $FFFF (or otherwise
denoted by 0x0000 to 0xFFFF). Here is a map of all of gameboy memory
so you know what's going on inside.
FFFF |
Interrupt Enable Flag |
This is another I/O register,
which controls the interrupts. |
FF80-$FFFE |
Zero Page - 127 bytes |
Originally intended to be used as
127 bytes of stack space, this area is better suited for use as a
Zero-Page, or a quick RAM access area. |
$FF00-$FF7F |
Hardware I/O Registers |
This area contains all
the control registers for all the hardware on the GameBoy and is basically
a memory-mapped I/O area. Details on this area are below. |
$FEA0-$FEFF |
Unusable Memory |
Just a small useless chunk left over.
Don't expect there to be ram here. |
$FE00-$FE9F |
OAM - Object Attribute Memory |
OAM is sprite RAM. This area is 40
sprites X 4 bytes long. When you with to display an object (sprite)
you write 4 corresponding bytes to OAM. These 4 bytes are explained
above. The tile number is taken from the Character RAM, just a BG
tiles are. The X and Y locations are slightly offset (8 pixels and
16 pixels), so you can have sprites partially off of the left and
top of the LCD. So if you set the location to 0,0 then the sprite
would be off of the screen. To set a sprite to the top-left corner,
you'd set it's location to 8,16. |
$E000-$FDFF |
Echo RAM - Reserved, Do Not Use |
This area echoes internal ram, but
is specified by Nintendo as reserved and shouldn't be used at all.
To keep with standards and to keep compatibility, don't use this area.
|
$D000-$DFFF |
Internal RAM - Bank 1-7 (switchable
- CGB only) |
If available. |
$C000-$CFFF |
Internal RAM - Bank 0 (fixed) |
This RAM in inside the GameBoy. Generally
used for most common variables and such in games. |
$A000-$BFFF |
Cartridge RAM (If Available) |
If present on the cartridge, this
area is mapped to the RAM on the cartridge. |
$9C00-$9FFF |
BG Map Data 2 |
This area is just a second background
map area like the previous one. To specify which map the video processor
uses to build the background image, change the apropriate bit in the
LCDC I/O register, explained later. |
$9800-$9BFF |
BG Map Data 1 |
This 1024-byte long area is what
the video processor uses to build the display. Each byte in this space
represnts an 8x8 pixel space on the display. This area is 32x32 tiles
large... EG: 1024 bytes. The display processor takes each byte and
then goes into the Character RAM area and gets the corresponding tile
from that area and draws it to the screen. So, if the first byte in
the Map area contained $40, the display processor would get tile $40
from the Character RAM and put it in the top-left corner of the virtual
screen. |
$8000-$97FF |
Character RAM |
This area is RAM inside the GB unit,
and is used exclusively for video purposes. This area is also known
as Tile RAM, since it holds tiles. Each tile is 8x8 pixels
of 2-bit color, which makes each tile 16 bytes long. This area is
also divided up into two modes of tiles, signed and unsigned. In unsigned
mode, tiles are numbered from 0-255 at $8000-$9000. In signed mode,
tiles are numbered in two's complement from -127 to 128 at $87FF-$97FF. |
$4000-$7FFF |
Cartridge ROM - Switchable Banks
1-xx |
This is where alot of your game data
will exist... in this 16K space. This area is switchable or banked.
You can switch in 16K chunks of the entire ROM in this area, through
the use of the Memory Bank Controller (MBC) on the cartridge. How
the MBC works is you basically "write" to an area in ROM,
and since ROM is by nature READ ONLY MEMORY, writing a value to ROM
is futile, except in the case of the MBC. It intercepts the attempted
write to ROM and interprets it into a bank switch. the value you try
to write to ROM is generally the bank number you want to change to.
|
$0150-$3FFF |
Cartridge ROM - Bank 0 (fixed) |
ROM Bank 0 is the home bank. It's
the fist 16K bank of any ROM image, and is a fixed bank, which means
you can't switch it out with other banks, like you can with the next
section (which is discussed in the next section). When the GameBoy
powers up, program execution starts at $0100, which almost always
has a jump to $0150 (jp $0150), the first byte of free space. So really,
$0150 will be the start of your programs. Since this bank is fixed
and CANNOT be changed out, it usually contains the majority of the
game's engine, or core routines. |
$0100-$014F |
Cartridge Header Area |
This area in the GameBoy address
space contains information about the cartridge that is inserted, including;
type of cartridge, size of rom, size of ram, a Nintendo logo, and
other information. Also, at $0100, there is a NOP instruction, followed
by a JUMP to the start of the program, usually $0150. The GameBoy's
CPU begins execution at $0100, that is why this is included. If the
Nintendo logo bytes are not correct, the GameBoy will not execute
the game. Upon power up, the system ROM in a GameBoy will verify that
the logo is correct. Nintendo has tried to use the logo to keep only
authorized developers from publishing games, since the logo is a registered
trademark of Nintendo. But, a legal precedent was set in the United
States in a case of Sega vs. Accolade (c.1993). Sega's Genesis console
also has a signature that is a copyright of Sega, and Accolade used
this logo so that their games, which were not approved by Sega, would
be able to play on the Genesis console. The judge ruled in favor of
Accolade, stating that using a logo to that degree was an anti competetive
practice, and therefore, Accolade was allowed to continue selling
their games. |
$0000-$00FF |
Restart and Interrupt
Vectors |
The first 255 byte area
in the Gameboy address space is reserved for Interrupt Vectors and
Restart Vectors. Interrupts are a break in program code generated
by a piece of the hardware when a certain condition is met. These
conditions can be set by the programmer. There are several different
types of interrupts, and when an interrupt is generated, the program
stops where it is, and jumps to one of the specified locations in
the Vector Table. |
|
I/O Registers |
|
The GameBoy has instructions & registers similar
to the Intel 8080, Intel 8085, & Zilog Z80 microprocessors. It has
eight 8-bit general purpose registers A,B,C,D,E,F,H,L and two 16-bit
registers SP & PC. Some instructions, however, allow you to use the
registers A,B,C,D,E,H, & L as 16-bit registers by pairing them up
in the following manner: AF,BC,DE, & HL. The PC, or Program Counter,
register points to the next instruction to be executed in the GameBoy
memory. The SP, or Stack Pointer, register points to the current
stack position. F is the Flag Register and contains the following
flags:
- Zero Flag (Z) - This bit is set when the result
of a math operation is zero or two values match when using the CP instruction.
- Subtract Flag (N) - This bit is set if a subtraction
was performed in the last math instruction.
- Half Carry Flag (H) - This bit is set if a carry
occurred from the lower nibble in the last math operation.
- Carry Flag (C) - This bit is set if a carry occurred
from the last math operation or if register A is the smaller value when
executing the CP instruction.
The GBC also has, in the address range $FF00-$FF7F,
memory mapped I/O registers which control all aspects of gameboy
hardware: the LCD, speaker, joypad, etc.
[$FF00]
; P1
|
Register
for reading joy pad info
and determining system type. |
Bit 7 - Not used
Bit 6 - Not used
Bit 5 - P15 out port
Bit 4 - P14 out port
Bit 3 - P13 in port
Bit 2 - P12 in port
Bit 1 - P11 in port
Bit 0 - P10 in port |
[$FF01]
; SB
|
Serial transfer
data (R/W)
|
Don't worry about this. |
[$FF02]; SC |
SIO control (R/W) |
Don't worry about this. |
[$FF04];
DIV |
Divider Register
(R/W) |
This register is incremented
16384 times a second. Writing any value sets it to $00. |
[$FF05]
= $00 ; TIMA |
Timer counter
(R/W)
|
This timer is incremented
by a clock frequency specified by the TAC register ($FF07). The timer
generates an interrupt when it overflows. |
[$FF06] = $00 ; TMA |
Timer Modulo (R/W)
|
When the TIMA overflows, this data
will be loaded. |
[$FF07]
= $00 ; TAC |
Timer Control
(R/W) |
Bit 2 - Timer Stop
0: Stop Timer
1: Start Timer
Bits 1+0 - Input Clock Select
00: 4.096 KHz
01: 262.144 KHz
10: 65.536 KHz
11: 16.384 KHz
|
[$FF0F];
IF
|
Interrupt
Flag (R/W) |
Bit 4: Transition from High to Low of Pin number
P10-P13
Bit 3: Serial I/O transfer complete
Bit 2: Timer Overflow
Bit 1: LCDC (see STAT)
Bit 0: V-Blank
|
[$FF10] = $80 ; NR10 |
Sound Registers. |
Don't worry
about these. |
[$FF11] = $BF ; NR11 |
[$FF12] = $F3 ; NR12 |
[$FF14] = $BF ; NR14 |
[$FF16] = $3F ; NR21 |
[$FF17] = $00 ; NR22 |
[$FF19] = $BF ; NR24 |
[$FF1A] = $7F ; NR30 |
[$FF1B] = $FF ; NR31 |
[$FF1C] = $9F ; NR32 |
[$FF1E] = $BF ; NR33 |
[$FF20] = $FF ; NR41 |
[$FF21] = $00 ; NR42 |
[$FF22] = $00 ; NR43 |
[$FF23] = $BF ; NR30 |
[$FF24] = $77 ; NR50 |
[$FF25] = $F3 ; NR51 |
[$FF26] = $F1-GB; NR52 |
[$FF40]
= $91 ; LCDC |
LCD Control
(R/W) - value $91 at reset of GBC |
Bit 7 - LCD Control
Operation
0: Stop completely (no picture on screen)
1: operation
Bit 6 - Window Tile Map Display Select
0: $9800-$9BFF
1: $9C00-$9FFF
Bit 5 - Window Display
0: off
1: on
Bit 4 - BG & Window Tile Data Select
0: $8800-$97FF
1: $8000-$8FFF <- Same area as OBJ
Bit 3 - BG Tile Map Display Select
0: $9800-$9BFF
1: $9C00-$9FFF
Bit 2 - OBJ (Sprite) Size
0: 8*8
1: 8*16 (width*height)
Bit 1 - OBJ (Sprite) Display
0: off
1: on
Bit 0 - BG Display
0: off
1: on
|
[$FF41] ; Stat |
LCDC Status |
Don't worry about this. |
[$FF42] =
$00 ; SCY |
Scroll Y
(R/W) |
8 Bit value $00-$FF to
scroll BG Y screen
position. |
[$FF43] = $00 ; SCX |
Scroll X (R/W) |
8 Bit value $00-$FF to scroll BG
X screen
position. |
[$FF47] =
$FC ; BGP |
BG &
Window Palette Data (R/W) |
Bit 7-6 - Data for Dot
Data 11 (Normally darkest color)
Bit 5-4 - Data for Dot Data 10
Bit 3-2 - Data for Dot Data 01
Bit 1-0 - Data for Dot Data 00 (Normally lightest color) |
[$FF48] = $FF ; OBP0 |
Object Palette 0 Data
(R/W) |
This selects the colors for sprite
palette 0.
It works exactly as BGP ($FF47) except each
each value of 0 is transparent. |
[$FF49] = $FF ; OBP1 |
Object Palette 1 Data
(R/W) |
This Selects the colors for sprite
palette 1.
It works exactly as OBP0 ($FF48).
See BGP for details. |
[$FF4A]
= $00 ; WY |
Window Y
Position (R/W) |
0 <= WY <= 143
WY must be greater than or equal to 0 and
must be less than or equal to 143 for
window to be visible.
|
[$FF4B] =
$00 ; WX |
Window X
Position (R/W) |
0 <= WX <= 166
WX must be greater than or equal to 0 and
must be less than or equal to 166 for
window to be visible.
WX is offset from absolute screen coordinates
by 7. Setting the window to WX=7, WY=0 will
put the upper left corner of the window at
absolute screen coordinates 0,0.
|
[$FFFF] = $00 ; IE |
Interrupt Enable (R/W) |
Bit 4: Transition from High to Low
of Pin
number P10-P13.
Bit 3: Serial I/O transfer complete
Bit 2: Timer Overflow
Bit 1: LCDC (see STAT)
Bit 0: V-Blank
0: disable
1: enable
|
|
Final Remarks |
|
Don't be alarmed by all this information. It's mostly
there just as reference. You should have mastered the ideas presented
in "Basic Concepts" because these are needed to program this
system. Also, you should have a general knowledge of the memory map. The
I/O Register table is mostly here for completeness. However, also be aware
that we need to know some of the I/O registers to properly set
up windows and backgrounds (yes we can directly manipulate the registers
in GBDK via ANDing and ORing bitmasks to the registers using the &
and | operator). Pay special attention to the LCDC register as
this is the key to controlling the LCD.
Well, this is almost all the information that defines
a gameboy. It's definitely enough for us to write a game. Mostly, this
information is essential to assembly programmers (and I don't think we'll
be doing any ASM coding, but I could be wrong). However, if you want the
technical reference document for the gameboy consult the so-called PanDoc
available here. It is the de facto standard for gameboy internals.
Well, that's enough of hardware. On to coding.
|